﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System;
using System.Windows;
using System.Windows.Controls;
using ScrumTable.BL.DM.DataManagement;
using ScrumTable.Common.Collections;
using ScrumTable.UI.View.Util;
using ScrumTable.UI.View.WinTouch.UserControls.Tool;
using ScrumTable.UI.ViewModel;
using ScrumTable.UI.ViewModel.Data;

#endregion

namespace ScrumTable.UI.View.WinTouch.UserControls.Menu
{
    /// <summary>
    /// DropControl. Use this class for showing a dropping control
    /// </summary>
    public class ContextMenu : UserControl
    {

        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------
        private FrameworkElement _parent;
        private StackPanel _listBoxStates;
        private StackPanel _viewModelSpecific;

        #endregion
        
        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------
     
        public ScrumViewModelData ScrumData
        {
            get { return ((AppScreen) Application.Current.MainWindow).ScrumData; }
        }

        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        public ContextMenu(FrameworkElement parent, object viewModel)
        {
            _parent = parent;
            Grid grid = new Grid();
            grid.RowDefinitions.Add(new RowDefinition() { MinHeight = 40 });
            grid.RowDefinitions.Add(new RowDefinition() { MinHeight = 40});
            grid.RowDefinitions.Add(new RowDefinition() { MinHeight = _parent.ActualHeight });
            grid.RowDefinitions.Add(new RowDefinition() { MinHeight = 40 });
            grid.RowDefinitions.Add(new RowDefinition() { MinHeight = 40 });

            _listBoxStates = new StackPanel() { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Top };
            _viewModelSpecific = new StackPanel() { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Top };
            Grid.SetRow(_viewModelSpecific, 3);
            Grid.SetRow(_listBoxStates, 1);
            
            grid.Children.Add(_listBoxStates);
            grid.Children.Add(_viewModelSpecific);

            if (viewModel is UserStoryViewModel)
            {
                UserStoryViewModel story = (UserStoryViewModel) viewModel;
                foreach (var state in ScrumData.CurrentProject.Types.UserStoryType.StateMappings)
                {
                    _listBoxStates.Children.Add(new DropStateControlDrop(UserStoryViewModel.CanChangeState, state, story));
                }

                DomainCollection<DomainMeta> domainCollection = ((UserStoryViewModel) viewModel).Original.ItemType.FieldMeta;
                AddSpecfic<UserStoryViewModel>(((UserStoryViewModel) viewModel), domainCollection);

            }
            else if (viewModel is TaskViewModel)
            {
                TaskViewModel task = (TaskViewModel)viewModel;

                foreach (var state in ScrumData.CurrentProject.Types.TaskType.StateMappings)
                {
                    _listBoxStates.Children.Add(new DropStateControlDrop(TaskViewModel.CanChangeState, state, task));
                }


                DomainCollection<DomainMeta> domainCollection = ((TaskViewModel)viewModel).Original.ItemType.FieldMeta;
                AddSpecfic<TaskViewModel>(((TaskViewModel)viewModel), domainCollection, "Priority");
            }
            else if (viewModel is BugViewModel)
            {
                BugViewModel bug = (BugViewModel)viewModel;

                foreach (var state in ScrumData.CurrentProject.Types.BugType.StateMappings)
                {
                    _listBoxStates.Children.Add(new DropStateControlDrop(BugViewModel.CanChangeState, state, bug));
                }

                DomainCollection<DomainMeta> domainCollection = ((BugViewModel)viewModel).Original.ItemType.FieldMeta;
                AddSpecfic<BugViewModel>(((BugViewModel)viewModel), domainCollection);
            }
            Content = grid;

            HorizontalAlignment = HorizontalAlignment.Left;
            VerticalAlignment = VerticalAlignment.Top;

            Point point = _parent.PointToScreen(new Point(0, 0));
            Margin = new Thickness(point.X, point.Y, 0, 0);
            Loaded += new RoutedEventHandler(OnControlLoaded);
        }


        private void AddSpecfic<T>(IScrumItemViewModel<DomainBase> item, DomainCollection<DomainMeta> domainCollection, string name=null)
        {
            if(name != null)
            {
                DomainMeta meta = domainCollection.TryGetByName(name);
                if( meta != null)
                {
                    AddValuesToList<T>(item, meta);
                    return;
                }
            }

            foreach (var meta in domainCollection)
            {
                if (!meta.AllowedValues.IsEmpty() && meta.Name != "State")
                {
                    AddValuesToList<T>(item, meta);
                    return;
                }
            }
        }
        
        private void AddValuesToList<T>(IScrumItemViewModel<DomainBase> item, DomainMeta meta)
        {
            foreach (var x in meta.AllowedValues)
            {
                DomainMeta meta3 = meta;
                _viewModelSpecific.Children.Add(new DropSpecificControl((a) => a is T, x, (c) => item[meta3.Name] = c));
            }
        }
        #endregion




        #region Methods
   
      
        #endregion


        #region Events

        private void OnControlLoaded(object sender, RoutedEventArgs e)
        {

            Height = _parent.Width + 4 * 40;
            Width = Math.Max(_listBoxStates.Children.Count, _viewModelSpecific.Children.Count) * 100;

            var screenGrid = ViewElementUtils.FindVisualParent(typeof(ScreenGrid), _parent) as ScreenGrid;
            FrameworkElement parentContainer = (FrameworkElement)screenGrid ?? Application.Current.MainWindow;
            Point x = TranslatePoint(new Point(0, 0), parentContainer);

            Point point = _parent.PointToScreen(new Point(0, 0));

            bool hasEnoughSpaceLeftSide = x.X > 100;
            double yOffset = hasEnoughSpaceLeftSide ? (Width - _parent.ActualWidth) / 2 : 0;

            bool hasEnoughSpaceRightSide = (parentContainer.ActualWidth - x.X > Width);
            yOffset = hasEnoughSpaceRightSide ? yOffset : Width - _parent.ActualWidth;

            if (!hasEnoughSpaceLeftSide)
            {
                _listBoxStates.HorizontalAlignment = _viewModelSpecific.HorizontalAlignment = HorizontalAlignment.Left;
            }

            if(!hasEnoughSpaceRightSide)
            {
                _listBoxStates.HorizontalAlignment = _viewModelSpecific.HorizontalAlignment = HorizontalAlignment.Right;
                
            }
            Margin = new Thickness(point.X - yOffset, point.Y - 80, 0, 0);

            Loaded -= OnControlLoaded;
            
            
            //set the correct row 
            Grid.SetRow(_listBoxStates,  (x.Y > 200) ? 1 : 4);
            Grid.SetRow(_viewModelSpecific, (parentContainer.ActualHeight - x.Y > 200) ? 3 : 0);

            


        }

        #endregion

    }
}
